var db = require('./db.js');

exports.Handler = require('jsonrpc').RPCHandler;

exports.methods = {
    addDepartamento: function(rpc, nome) {
        if (nome == null) {
            rpc.error('Incorrect params');
            return;
        }
        
        var departamento = new db.Departamento();
        departamento.nome = nome;

        departamento.save(function(err) {
            if (err == null) {
                rpc.response(departamento);
            } else {
                rpc.error('db access error');
            }
        });
    },
    editDepartamento: function(rpc, id, nome) {
        if (id == null || nome == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.findById(id, function(err, departamento) {
            if (err == null) {
                if (departamento != null) {
                    departamento.nome = nome;

                    departamento.save(function(err) {
                        if (err == null) {
                            rpc.response(departamento);
                        } else {
                            rpc.error('db access error');
                        }
                    });
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getDepartamentos: function(rpc) {
        db.Departamento.find({}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getDepartamentoById: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    rpc.response(doc);
                } else {
                    rpc.error('not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getDepartamentosByNome: function(rpc, nome) {
        if (nome == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.find({'nome': nome}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    removeDepartamento: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    db.Professor
                        .find({'departamento': id},
                              function(err, docs) {
                                  if (err == null) {
                                      docs.forEach(function(professor) {
                                          professor.remove();
                                      });
                                  }
                              });

                    db.Curso
                        .find({'departamento': id},
                              function(err, docs) {
                                  if (err == null) {
                                      docs.forEach(function(curso) {
                                          curso.remove();
                                      });
                                  }
                              });

                    doc.remove();
                    rpc.response('ok');
                } else {
                    rpc.response('doesn\'t exists');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    addProfessor: function(rpc, nome, departamento) {
        if (nome == null || departamento == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.findById(departamento, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('departamento doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        var professor = new db.Professor();
        professor.nome = nome;
        professor.departamento = departamento;

        professor.save(function(err) {
            if (err == null) {
                rpc.response(professor);
            } else {
                rpc.error('db access error');
            }
        });
    },
    editProfessor: function(rpc, id, nome, departamento) {
        if (id == null || nome == null || departamento == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.findById(departamento, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('departamento doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        db.Professor.findById(id, function(err, professor) {
            if (err == null) {
                if (professor != null) {
                    professor.nome = nome;
                    professor.departamento = departamento;

                    professor.save(function(err) {
                        if (err == null) {
                            rpc.response(professor);
                        } else {
                            rpc.error('db access error');
                        }
                    });
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getProfessores: function(rpc) {
        db.Professor.find({}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getProfessoresByDepartamento: function(rpc, departamento) {
        if (departamento == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Professor.find({'departamento': departamento}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getProfessorById: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }
        
        db.Professor.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    rpc.response(doc);
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getProfessoresByNome: function(rpc, nome) {
        if (nome == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Professor.find({'nome': nome}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    removeProfessor: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Professor.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    db.Disciplina
                        .find({'professor': id},
                              function(err, docs) {
                                  if (err == null) {
                                      docs.forEach(function(disciplina) {
                                          disciplina.remove();
                                      });
                                  }
                              });

                    doc.remove();
                    rpc.response('ok');
                } else {
                    rpc.response('doesn\'t exists');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    addCurso: function(rpc, nome, departamento, pos) {
        if (nome == null || departamento == null || pos == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.findById(departamento, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('departamento doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        var curso = new db.Curso();
        curso.nome = nome;
        curso.departamento = departamento;
        curso.pos = pos;

        curso.save(function(err) {
            if (err == null) {
                rpc.response(curso);
            } else {
                rpc.error('db access error');
            }
        });
    },
    editCurso: function(rpc, id, nome, departamento, pos) {
        if (id == null
            || nome == null
            || departamento == null
            || pos == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Departamento.findById(departamento, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('departamento doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        db.Curso.findById(id, function(err, curso) {
            if (err == null) {
                if (curso != null) {
                    curso.nome = nome;
                    curso.departamento = departamento;
                    curso.pos = pos;

                    curso.save(function(err) {
                        if (err == null) {
                            rpc.response(curso);
                        } else {
                            rpc.error('db access error');
                        }
                    });
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getCursos: function(rpc) {
        db.Curso.find({}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getCursosByDepartamento: function(rpc, departamento) {
        if (departamento == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Curso.find({'departamento': departamento}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getCursoById: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }
        
        db.Curso.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    rpc.response(doc);
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getCursosByNome: function(rpc, nome) {
        if (nome == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Curso.find({'nome': nome}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    removeCurso: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Curso.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    db.Aluno
                        .find({'curso': id},
                              function(err, docs) {
                                  if (err == null) {
                                      docs.forEach(function(aluno){
                                          aluno.remove();
                                      });
                                  }
                              });

                    db.Disciplina
                        .find({'curso': id},
                              function(err, docs) {
                                  if (err == null) {
                                      docs.forEach(function(disciplina){
                                          disciplina.remove();
                                      });
                                  }
                              });

                    doc.remove();
                    rpc.response('ok');
                } else {
                    rpc.response('doesn\'t exists');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    addAluno: function(rpc, nome, curso) {
        if (nome == null || curso == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Curso.findById(curso, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('curso doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        var aluno = new db.Aluno();
        aluno.nome = nome;
        aluno.curso = curso;

        aluno.save(function(err) {
            if (err == null) {
                rpc.response(aluno);
            } else {
                rpc.error('db access error');
            }
        });
    },
    editAluno: function(rpc, id, nome, curso) {
        if (id == null || nome == null || curso == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Curso.findById(curso, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('curso doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        db.Aluno.findById(id, function(err, aluno) {
            if (err == null) {
                if (aluno != null) {
                    aluno.nome = nome;
                    aluno.curso = curso;

                    aluno.save(function(err) {
                        if (err == null) {
                            rpc.response(aluno);
                        } else {
                            rpc.error('db access error');
                        }
                    });
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getAlunos: function(rpc) {
        db.Aluno.find({}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getAlunosByCurso: function(rpc, curso) {
        if (curso == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Aluno.find({'curso': curso}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getAlunoById: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }
        
        db.Aluno.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    rpc.response(doc);
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getAlunosByNome: function(rpc, nome) {
        if (nome == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Aluno.find({'nome': nome}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    removeAluno: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Aluno.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    doc.remove();
                    rpc.response('ok');
                } else {
                    rpc.response('doesn\'t exists');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    addDisciplina: function(rpc,
                            nome,
                            creditosFornecidos,
                            creditosNecessarios,
                            curso,
                            professor,
                            obrigatoria) {
        if (nome == null
            || creditosFornecidos == null
            || creditosNecessarios == null
            || curso == null
            || professor == null
            || obrigatoria == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Curso.findById(curso, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('curso doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        db.Professor.findById(professor, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('professor doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        var disciplina = new db.Disciplina();
        disciplina.nome = nome;
        disciplina.creditosFornecidos = creditosFornecidos;
        disciplina.creditosNecessarios = creditosNecessarios;
        disciplina.curso = curso;
        disciplina.professor = professor;
        disciplina.obrigatoria = obrigatoria;

        disciplina.save(function(err) {
            if (err == null) {
                rpc.response(disciplina);
            } else {
                rpc.error('db access error');
            }
        });
    },
    editDisciplina: function(rpc,
                             id,
                             nome,
                             creditosFornecidos,
                             creditosNecessarios,
                             curso,
                             professor,
                             obrigatoria) {
        if (id == null
            || nome == null
            || creditosFornecidos == null
            || creditosNecessarios == null
            || curso == null
            || professor == null
            || obrigatoria == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Curso.findById(curso, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('curso doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        db.Professor.findById(professor, function(err, doc) {
            if (err == null) {
                if (doc == null) {
                    rpc.error('professor doesn\'t exists');
                    return;
                }
            } else {
                rpc.error('db access error');
                return;
            }
        });

        db.Disciplina.findById(id, function(err, disciplina) {
            if (err == null) {
                if (disciplina != null) {
                    disciplina.nome = nome;
                    disciplina.creditosFornecidos = creditosFornecidos;
                    disciplina.creditosNecessarios = creditosNecessarios;
                    disciplina.curso = curso;
                    disciplina.professor = professor;
                    disciplina.obrigatoria = obrigatoria;

                    disciplina.save(function(err) {
                        if (err == null) {
                            rpc.response(disciplina);
                        } else {
                            rpc.error('db access error');
                        }
                    });
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getDisciplinas: function(rpc) {
        db.Disciplina.find({}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getDisciplinasByCurso: function(rpc, curso) {
        if (curso == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Disciplina.find({'curso': curso}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    getDisciplinaById: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }
        
        db.Disciplina.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    rpc.response(doc);
                } else {
                    rpc.error('Not found');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    getDisciplinasByNome: function(rpc, nome) {
        if (nome == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Disciplina.find({'nome': nome}, function(err, docs) {
            if (err == null) {
                rpc.response(docs);
            } else {
                rpc.error('db access error');
            }
        });
    },
    removeDisciplina: function(rpc, id) {
        if (id == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Disciplina.findById(id, function(err, doc) {
            if (err == null) {
                if (doc != null) {
                    doc.remove();
                    rpc.response('ok');
                } else {
                    rpc.response('doesn\'t exists');
                }
            } else {
                rpc.error('db access error');
            }
        });
    },
    // TODO: verificar se aluno já não estava matriculado nessa disciplina
    matricularAluno: function(rpc, alunoId, disciplinaId) {
        if (alunoId == null || disciplinaId == null) {
            rpc.error('Incorrect params');
            return;
        }

        db.Aluno.findById(alunoId, function(err, aluno) {
            if (err == null) {
                if (aluno != null) {
                    db.Disciplina.findById(disciplinaId, function(err, disciplina) {
                        if (err == null) {
                            if (disciplina != null) {
                                if (aluno.creditosEmObrigatorias + aluno.creditosEmEletivas
                                    >= disciplina.creditosNecessarios) {
                                    disciplina.disciplinasNecessarias.forEach(function(dep) {
                                        if (aluno.disciplinasPagas.indexOf(dep) == -1) {
                                            rpc.error('Dependencia nao satisfeita');
                                            return;
                                        }
                                    });
                                    aluno.disciplinasAtuais.push(disciplinaId);
                                    aluno.save(function(err) {
                                        if (err == null) {
                                            rpc.response('ok');
                                        } else {
                                            rpc.error('db access error');
                                        }
                                    });
                                } else {
                                    rpc.error('Creditos insuficientes');
                                }
                            } else {
                                rpc.response('doesn\'t exists');
                            }
                        } else {
                            rpc.error('db access error');
                        } 
                    });
                } else {
                    rpc.response('doesn\'t exists');
                }
            } else {
                rpc.error('db access error');
            }
        });
    }/*,
    reset: function(rpc) {
        db.Departamento.find({}, function(err, docs) {
            if (!err) {
                docs.forEach(function(doc) {
                    doc.remove();
                });
            } else {
                rpc.error('db acess error');
                return;
            }
        });
        db.Professor.find({}, function(err, docs) {
            if (!err) {
                docs.forEach(function(doc) {
                    doc.remove();
                });
            } else {
                rpc.error('db acess error');
                return;
            }
        });
        db.Curso.find({}, function(err, docs) {
            if (!err) {
                docs.forEach(function(doc) {
                    doc.remove();
                });
            } else {
                rpc.error('db acess error');
                return;
            }
        });
        db.Aluno.find({}, function(err, docs) {
            if (!err) {
                docs.forEach(function(doc) {
                    doc.remove();
                });
            } else {
                rpc.error('db acess error');
                return;
            }
        });
        db.Disciplina.find({}, function(err, docs) {
            if (!err) {
                docs.forEach(function(doc) {
                    doc.remove();
                });
            } else {
                rpc.error('db acess error');
                return;
            }
        });
        rpc.response('ok');
    }*/
}
